﻿using System;
using System.Timers;
using System.Threading;

namespace IOP.Models
{
    /// <summary>
    /// 重复任务
    /// </summary>
    public class RepeatTask : IDisposable
    {
        /// <summary>
        /// 任务ID
        /// </summary>
        public readonly Guid TaskId = Guid.NewGuid();
        /// <summary>
        /// 重复次数
        /// </summary>
        public int RepeatCount { get; set; }
        /// <summary>
        /// 重复间隔
        /// </summary>
        public double Interval { get; set; }
        /// <summary>
        /// 是否正在运行
        /// </summary>
        public bool IsRunning {
            get
            {
                return Volatile.Read(ref isRunning);
            }
        }
        /// <summary>
        /// 运行结束时处理函数
        /// </summary>
        public Action OnRunningFinish{ get; set; }
        /// <summary>
        /// 运行中断时处理函数
        /// </summary>
        public Action OnRunningInterrupt { get; set; }
        /// <summary>
        /// 执行函数
        /// </summary>
        private Action ExecuteHandle;
        /// <summary>
        /// 计时器
        /// </summary>
        private readonly System.Timers.Timer Timer = new System.Timers.Timer();
        private int ExecuteCount = 0;
        private readonly object SyncRoot = new object();
        private bool isRunning = false;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="repeatCount"></param>
        /// <param name="interval"></param>
        public RepeatTask(int repeatCount = 3, double interval = 10000)
        {
            RepeatCount = repeatCount;
            Interval = interval;
            Timer.Elapsed += TimerTask;
        }
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="task"></param>
        /// <param name="repeatCount"></param>
        /// <param name="interval"></param>
        public RepeatTask(Action task, int repeatCount = 3, double interval = 10000)
        {
            ExecuteHandle = task;
            RepeatCount = repeatCount;
            Interval = interval;
            Timer.Elapsed += TimerTask;

        }

        /// <summary>
        /// 执行任务
        /// </summary>
        public void RunTask() => Start();
        /// <summary>
        /// 执行任务
        /// </summary>
        public void RunTask(Action task)
        {
            ExecuteHandle = task;
            Start();
        }
        /// <summary>
        /// 中断
        /// </summary>
        public void Interrupt() => Stop();
        /// <summary>
        /// 完成
        /// </summary>
        public void Finish() => Stop();
        /// <summary>
        /// 停止
        /// </summary>
        private void Stop()
        {
            if (!Volatile.Read(ref isRunning)) return;
            lock (SyncRoot)
            {
                Timer.Stop();
                Volatile.Write(ref isRunning, false);
                ExecuteCount = 0;
                OnRunningFinish?.Invoke();
            }
        }


        /// <summary>
        /// 启动定时器
        /// </summary>
        private void Start()
        {
            if (Volatile.Read(ref isRunning)) return;
            lock(SyncRoot)
            {
                Volatile.Write(ref isRunning, true);
                Timer.Interval = Interval;
                Timer.Stop();
                Timer.Start();
            }
        }
        /// <summary>
        /// 定时器任务
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void TimerTask(object sender, ElapsedEventArgs e)
        {
            if (ExecuteCount < RepeatCount)
            {
                ExecuteHandle?.Invoke();
                ExecuteCount++;
            }
            else Finish();
        }

        /// <summary>
        /// 销毁资源
        /// </summary>
        public void Dispose()
        {
            ExecuteHandle = null;
            OnRunningFinish = null;
            OnRunningInterrupt = null;
            Timer.Stop();
            Timer.Elapsed -= TimerTask;
            Timer.Dispose();
        }
    }
}
